home *** CD-ROM | disk | FTP | other *** search
- #if !defined(lint) && !defined(DOS)
- static char rcsid[] = "$Id: ttyin.c,v 4.121 1996/03/15 07:13:42 hubert Exp $";
- #endif
- /*----------------------------------------------------------------------
-
- T H E P I N E M A I L S Y S T E M
-
- Laurence Lundblade and Mike Seibel
- Networks and Distributed Computing
- Computing and Communications
- University of Washington
- Administration Builiding, AG-44
- Seattle, Washington, 98195, USA
- Internet: lgl@CAC.Washington.EDU
- mikes@CAC.Washington.EDU
-
- Please address all bugs and comments to "pine-bugs@cac.washington.edu"
-
-
- Pine and Pico are registered trademarks of the University of Washington.
- No commercial use of these trademarks may be made without prior written
- permission of the University of Washington.
-
- Pine, Pico, and Pilot software and its included text are Copyright
- 1989-1996 by the University of Washington.
-
- The full text of our legal notices is contained in the file called
- CPYRIGHT, included with this distribution.
-
-
- Pine is in part based on The Elm Mail System:
- ***********************************************************************
- * The Elm Mail System - Revision: 2.13 *
- * *
- * Copyright (c) 1986, 1987 Dave Taylor *
- * Copyright (c) 1988, 1989 USENET Community Trust *
- ***********************************************************************
-
-
- ----------------------------------------------------------------------*/
-
- /*======================================================================
- ttyin.c
- Things having to do with reading from the tty driver and keyboard
- - initialize tty driver and reset tty driver
- - read a character from terminal with keyboard escape seqence mapping
- - initialize keyboard (keypad or such) and reset keyboard
- - prompt user for a line of input
- - read a command from keyboard with timeouts.
-
- ====*/
-
-
- /*
- * Helpful definitions
- */
- #define RETURN_CH(X) return(key_recorder((X), 0))
-
-
- #if !(defined(DOS) || defined(OS2))
- /* Beginning of giant switch between UNIX and DOS input driver */
-
- #include "headers.h"
-
- /*
- * Internal prototypes
- */
- void line_paint PROTO((int, int *));
- int process_config_input PROTO((int *));
- int getchar_for_kbseq PROTO ((void));
- int check_for_timeout PROTO((int));
- int read_a_char PROTO((void));
- void read_bail PROTO((void));
-
- #ifdef USE_POLL
- #include <stropts.h>
- #include <poll.h>
- #endif
-
- #ifdef HAVE_TERMIOS
- #include <termios.h>
-
- struct termios _raw_tty, _original_tty;
-
- #else
- #ifdef HAVE_TERMIO
- #include <termio.h>
-
- static struct termio _raw_tty, _original_tty;
-
-
- #else /* HAVE_TERMIO */
-
- #include <sgtty.h>
-
- static struct sgttyb _raw_tty, _original_tty;
- static struct ltchars _raw_ltchars, _original_ltchars;
- static struct tchars _raw_tchars, _original_tchars;
- static int _raw_lmode, _original_lmode;
- #endif /* HAVE_TERMIO */
- #endif /* HAVE_TERMIOS */
-
- /*
- * current raw state
- */
- static short _inraw = 0;
-
-
- #define STDIN_FD 0
- #define STDOUT_FD 1
-
- /*----------------------------------------------------------------------
- Initialize the tty driver to do single char I/O and whatever else (UNIX)
-
- Args: struct pine
-
- Result: tty driver is put in raw mode so characters can be read one
- at a time. Returns -1 if unsuccessful, 0 if successful.
-
- Some file descriptor voodoo to allow for pipes across vforks. See
- open_mailer for details.
- ----------------------------------------------------------------------*/
- init_tty_driver(ps)
- struct pine *ps;
- {
- #ifdef MOUSE
- if(F_ON(F_ENABLE_MOUSE, ps_global))
- if(init_mouse())
- kpinsert(&ps->kbesc, "\033[M", KEY_XTERM_MOUSE);
- #endif /* MOUSE */
-
- /* turn off talk permission by default */
-
- if(F_ON(F_ALLOW_TALK, ps))
- allow_talk(ps);
- else
- disallow_talk(ps);
-
- return(Raw(1));
- }
-
-
- /*----------------------------------------------------------------------
- Add the hardwired escape sequences to the keyboard escape sequence (UNIX)
- tree. This only needs to be here for people who don't have correct
- termcap/info entries for these, which is almost everybody. Since
- these get added after the termcap/info versions of the same thing,
- an escape sequence here that is the same as one there, or is a prefix
- of one, or is a superset of one, will override the one from termcap.
- So an incorrect termcap won't break things. A correct termcap entry
- that gets overwrote by an unfortunate coincidence will break things.
- In order to reverse the priority and have termcap/info entries override
- hardwired ones, define TERMCAP_WINS for os_unix.c in the
- pico subdirectory.
-
- Args: kbesc -- the trie used to store the escape sequences in
-
- Result: a fixed set of known escape sequences are added to the trie
- ----------------------------------------------------------------------*/
- void
- setup_dflt_esc_seq(kbesc)
- KBESC_T **kbesc;
- {
- /*
- * this is sort of a hack [no kidding], but it allows us to use
- * the function keys on pc's running telnet
- *
- * UW-NDC/UCS vt10[01] application mode.
- */
- kpinsert(kbesc, "\033OP", PF1);
- kpinsert(kbesc, "\033OQ", PF2);
- kpinsert(kbesc, "\033OR", PF3);
- kpinsert(kbesc, "\033OS", PF4);
- kpinsert(kbesc, "\033Op", PF5);
- kpinsert(kbesc, "\033Oq", PF6);
- kpinsert(kbesc, "\033Or", PF7);
- kpinsert(kbesc, "\033Os", PF8);
- kpinsert(kbesc, "\033Ot", PF9);
- kpinsert(kbesc, "\033Ou", PF10);
- kpinsert(kbesc, "\033Ov", PF11);
- kpinsert(kbesc, "\033Ow", PF12);
-
- /*
- * DEC vt100, ANSI and cursor key mode.
- */
- kpinsert(kbesc, "\033OA", KEY_UP);
- kpinsert(kbesc, "\033OB", KEY_DOWN);
- kpinsert(kbesc, "\033OC", KEY_RIGHT);
- kpinsert(kbesc, "\033OD", KEY_LEFT);
-
- /*
- * special keypad functions
- */
- kpinsert(kbesc, "\033[4J", KEY_PGUP);
- kpinsert(kbesc, "\033[3J", KEY_PGDN);
- kpinsert(kbesc, "\033[2J", KEY_HOME);
- kpinsert(kbesc, "\033[N", KEY_END);
-
- /*
- * ANSI mode.
- */
- kpinsert(kbesc, "\033[=a", PF1);
- kpinsert(kbesc, "\033[=b", PF2);
- kpinsert(kbesc, "\033[=c", PF3);
- kpinsert(kbesc, "\033[=d", PF4);
- kpinsert(kbesc, "\033[=e", PF5);
- kpinsert(kbesc, "\033[=f", PF6);
- kpinsert(kbesc, "\033[=g", PF7);
- kpinsert(kbesc, "\033[=h", PF8);
- kpinsert(kbesc, "\033[=i", PF9);
- kpinsert(kbesc, "\033[=j", PF10);
- kpinsert(kbesc, "\033[=k", PF11);
- kpinsert(kbesc, "\033[=l", PF12);
-
- /*
- * DEC vt100, ANSI and cursor key mode reset
- */
- kpinsert(kbesc, "\033[A", KEY_UP);
- kpinsert(kbesc, "\033[B", KEY_DOWN);
- kpinsert(kbesc, "\033[C", KEY_RIGHT);
- kpinsert(kbesc, "\033[D", KEY_LEFT);
-
- /*
- * DEC vt52 mode.
- */
- kpinsert(kbesc, "\033A", KEY_UP);
- kpinsert(kbesc, "\033B", KEY_DOWN);
- kpinsert(kbesc, "\033C", KEY_RIGHT);
- kpinsert(kbesc, "\033D", KEY_LEFT);
-
- /*
- * DEC vt52 application keys, and some Zenith 19.
- */
- kpinsert(kbesc, "\033?r", KEY_DOWN);
- kpinsert(kbesc, "\033?t", KEY_LEFT);
- kpinsert(kbesc, "\033?v", KEY_RIGHT);
- kpinsert(kbesc, "\033?x", KEY_UP);
-
- /*
- * Sun Console sequences.
- */
- kpinsert(kbesc, "\033[1", KEY_SWALLOW_Z);
- kpinsert(kbesc, "\033[215", KEY_SWAL_UP);
- kpinsert(kbesc, "\033[217", KEY_SWAL_LEFT);
- kpinsert(kbesc, "\033[219", KEY_SWAL_RIGHT);
- kpinsert(kbesc, "\033[221", KEY_SWAL_DOWN);
-
- /*
- * Kermit App Prog Cmd, gobble until ESC \ (kermit should intercept this)
- */
- kpinsert(kbesc, "\033_", KEY_KERMIT);
-
- /*
- * Fake a control character.
- */
- kpinsert(kbesc, "\033\033", KEY_DOUBLE_ESC);
- }
-
-
-
- /*----------------------------------------------------------------------
- Set or clear the specified tty mode
-
- Args: ps -- struct pine
- mode -- mode bits to modify
- clear -- whether or not to clear or set
-
- Result: tty driver mode change.
- ----------------------------------------------------------------------*/
- void
- tty_chmod(ps, mode, func)
- struct pine *ps;
- int mode;
- int func;
- {
- char *tty_name;
- int new_mode;
- struct stat sbuf;
- static int saved_mode = -1;
-
- /* if no problem figuring out tty's name & mode? */
- if((((tty_name = (char *) ttyname(STDIN_FD)) != NULL
- && fstat(STDIN_FD, &sbuf) == 0)
- || ((tty_name = (char *) ttyname(STDOUT_FD)) != NULL
- && fstat(STDOUT_FD, &sbuf) == 0))
- && !(func == TMD_RESET && saved_mode < 0)){
- new_mode = (func == TMD_RESET)
- ? saved_mode
- : (func == TMD_CLEAR)
- ? (sbuf.st_mode & ~mode)
- : (sbuf.st_mode | mode);
- /* assign tty new mode */
- if(chmod(tty_name, new_mode) == 0){
- if(func == TMD_RESET) /* forget we knew */
- saved_mode = -1;
- else if(saved_mode < 0)
- saved_mode = sbuf.st_mode; /* remember original */
- }
- }
- }
-
-
-
- /*----------------------------------------------------------------------
- End use of the tty, put it back into it's normal mode (UNIX)
-
- Args: ps -- struct pine
-
- Result: tty driver mode change.
- ----------------------------------------------------------------------*/
- void
- end_tty_driver(ps)
- struct pine *ps;
- {
- ps = ps; /* get rid of unused parameter warning */
-
- #ifdef MOUSE
- end_mouse();
- #endif /* MOUSE */
- fflush(stdout);
- dprint(2, (debugfile, "about to end_tty_driver\n"));
-
- tty_chmod(ps, 0, TMD_RESET);
- Raw(0);
- }
-
-
-
- /*----------------------------------------------------------------------
- Actually set up the tty driver (UNIX)
-
- Args: state -- which state to put it in. 1 means go into raw, 0 out of
-
- Result: returns 0 if successful and -1 if not.
- ----*/
-
- Raw(state)
- int state;
- {
- /** state is either ON or OFF, as indicated by call **/
- /* Check return code only on first call. If it fails we're done for and
- if it goes OK the other will probably go OK too. */
-
- if (state == 0 && _inraw) {
- /*----- restore state to original -----*/
- #ifdef HAVE_TERMIOS
- if (tcsetattr (STDIN_FD, TCSADRAIN, &_original_tty) < 0)
- return -1;
- #else /* HAVE_TERMIOS */
- #ifdef HAVE_TERMIO
- if(ioctl(STDIN_FD, TCSETAW, &_original_tty) < 0)
- return(-1);
- #else
- if(ioctl(STDIN_FD, TIOCSETP, &_original_tty) < 0)
- return(-1);
- (void) ioctl(STDIN_FD, TIOCSLTC, &_original_ltchars);
- (void) ioctl(STDIN_FD, TIOCSETC, &_original_tchars);
- (void) ioctl(STDIN_FD, TIOCLSET, &_original_lmode);
- #endif /* HAVE_TERMIO */
- #endif /* HAVE_TERMIOS */
- _inraw = 0;
- } else if (state == 1 && ! _inraw) {
- /*----- Go into raw mode (cbreak actually) ----*/
-
- #ifdef HAVE_TERMIOS
- if (tcgetattr (STDIN_FD, &_original_tty) < 0)
- return -1;
- tcgetattr (STDIN_FD, &_raw_tty);
- _raw_tty.c_lflag &= ~(ICANON | ECHO | IEXTEN); /* noecho raw mode */
-
- _raw_tty.c_lflag &= ~ISIG; /* disable signals */
- _raw_tty.c_iflag &= ~ICRNL; /* turn off CR->NL on input */
- _raw_tty.c_oflag &= ~ONLCR; /* turn off NL->CR on output */
-
- /* Only go into 8 bit mode if we are doing something other
- * than plain ASCII. This will save the folks that have
- * their parity on their serial lines wrong thr trouble of
- * getting it right
- */
- if(ps_global->VAR_CHAR_SET && ps_global->VAR_CHAR_SET[0] &&
- strucmp(ps_global->VAR_CHAR_SET, "us-ascii"))
- _raw_tty.c_iflag &= ~ISTRIP; /* turn off hi bit stripping */
-
- _raw_tty.c_cc[VMIN] = '\01'; /* min # of chars to queue */
- _raw_tty.c_cc[VTIME] = '\0'; /* min time to wait for input*/
- _raw_tty.c_cc[VINTR] = 0;
- _raw_tty.c_cc[VQUIT] = 0;
- _raw_tty.c_cc[VSUSP] = 0;
- ps_global->low_speed = cfgetospeed(&_raw_tty) < B4800;
- tcsetattr (STDIN_FD, TCSADRAIN, &_raw_tty);
- #else
- #ifdef HAVE_TERMIO
- if(ioctl(STDIN_FD, TCGETA, &_original_tty) < 0)
- return(-1);
- (void) ioctl(STDIN_FD, TCGETA, &_raw_tty); /** again! **/
-
- _raw_tty.c_lflag &= ~(ICANON | ECHO); /* noecho raw mode */
-
- _raw_tty.c_lflag &= ~ISIG; /* disable signals */
-
- _raw_tty.c_iflag &= ~ICRNL; /* turn off CR->NL on input */
- _raw_tty.c_oflag &= ~ONLCR; /* turn off NL->CR on output */
- _raw_tty.c_cc[VMIN] = 1; /* min # of chars to queue */
- _raw_tty.c_cc[VTIME] = 0; /* min time to wait for input*/
- _raw_tty.c_cc[VINTR] = 0;
- _raw_tty.c_cc[VQUIT] = 0;
- ps_global->low_speed = (_raw_tty.c_cflag&CBAUD) < (unsigned int)B4800;
- (void) ioctl(STDIN_FD, TCSETAW, &_raw_tty);
-
- #else /* HAVE_TERMIO */
- if(ioctl(STDIN_FD, TIOCGETP, &_original_tty) < 0)
- return(-1);
- (void) ioctl(STDIN_FD, TIOCGETP, &_raw_tty);
- (void) ioctl(STDIN_FD, TIOCGETC, &_original_tchars);
- (void) ioctl(STDIN_FD, TIOCGETC, &_raw_tchars);
- (void) ioctl(STDIN_FD, TIOCGLTC, &_original_ltchars);
- (void) ioctl(STDIN_FD, TIOCGLTC, &_raw_ltchars);
- (void) ioctl(STDIN_FD, TIOCLGET, &_original_lmode);
- (void) ioctl(STDIN_FD, TIOCLGET, &_raw_lmode);
-
- _raw_tty.sg_flags &= ~(ECHO); /* echo off */
- _raw_tty.sg_flags |= CBREAK; /* raw on */
- _raw_tty.sg_flags &= ~CRMOD; /* Turn off CR -> LF mapping */
-
- _raw_tchars.t_intrc = -1; /* Turn off ^C and ^D */
- _raw_tchars.t_eofc = -1;
-
- #ifdef DEBUG
- if(debug < 9) /* only on if full debugging set */
- #endif
- _raw_tchars.t_quitc = -1; /* Turn off ^\ */
-
- _raw_ltchars.t_lnextc = -1; /* Turn off ^V so we can use it */
- _raw_ltchars.t_dsuspc = -1; /* Turn off ^Y so we can use it */
- _raw_ltchars.t_suspc = -1; /* Turn off ^Z; we just read 'em */
- _raw_ltchars.t_werasc = -1; /* Turn off ^w word erase */
- _raw_ltchars.t_rprntc = -1; /* Turn off ^R reprint line */
- _raw_ltchars.t_flushc = -1; /* Turn off ^O output flush */
-
- /* Only go into 8 bit mode if we are doing something other
- * than plain ASCII. This will save the folks that have
- * their parity on their serial lines wrong thr trouble of
- * getting it right
- */
- if(ps_global->VAR_CHAR_SET && ps_global->VAR_CHAR_SET[0] &&
- strucmp(ps_global->VAR_CHAR_SET, "us-ascii")) {
- _raw_lmode |= LPASS8;
- #ifdef NXT /* Hope there aren't many like this! */
- _raw_lmode |= LPASS8OUT;
- #endif
- }
-
- (void) ioctl(STDIN_FD, TIOCSETP, &_raw_tty);
- (void) ioctl(STDIN_FD, TIOCSLTC, &_raw_ltchars);
- (void) ioctl(STDIN_FD, TIOCSETC, &_raw_tchars);
- (void) ioctl(STDIN_FD, TIOCLSET, &_raw_lmode);
- ps_global->low_speed = (int)_raw_tty.sg_ispeed < B4800;
-
- #endif
- #endif
- _inraw = 1;
- crlf_proc(0);
- xonxoff_proc(F_ON(F_PRESERVE_START_STOP, ps_global));
- }
- return(0);
- }
-
-
-
- /*----------------------------------------------------------------------
- Set up the tty driver to use XON/XOFF flow control (UNIX)
-
- Args: state -- True to make sure XON/XOFF turned on, FALSE off.
-
- Result: none.
-
- ----*/
- void
- xonxoff_proc(state)
- int state;
- {
- if(_inraw){
- if(state){
- #ifdef HAVE_TERMIOS
- if(!(_raw_tty.c_iflag & IXON)){
- _raw_tty.c_iflag |= IXON;
- tcsetattr (STDIN_FD, TCSADRAIN, &_raw_tty);
- }
- #else
- #ifdef HAVE_TERMIO
- if(!(_raw_tty.c_iflag & IXON)){
- _raw_tty.c_iflag |= IXON; /* turn ON ^S/^Q on input */
- (void) ioctl(STDIN_FD, TCSETAW, &_raw_tty);
- }
- #else /* HAVE_TERMIO */
- if(_raw_tchars.t_startc == -1 || _raw_tchars.t_stopc == -1){
- _raw_tchars.t_startc = 'Q' - '@'; /* Turn ON ^S/^Q */
- _raw_tchars.t_stopc = 'S' - '@';
- (void) ioctl(STDIN_FD, TIOCSETC, &_raw_tchars);
- }
- #endif
- #endif
- }
- else if(F_OFF(F_PRESERVE_START_STOP, ps_global)){
- #ifdef HAVE_TERMIOS
- if(_raw_tty.c_iflag & IXON){
- _raw_tty.c_iflag &= ~IXON; /* turn off ^S/^Q on input */
- tcsetattr (STDIN_FD, TCSADRAIN, &_raw_tty);
- }
- #else
- #ifdef HAVE_TERMIO
- if(_raw_tty.c_iflag & IXON){
- _raw_tty.c_iflag &= ~IXON; /* turn off ^S/^Q on input */
- (void) ioctl(STDIN_FD, TCSETAW, &_raw_tty);
- }
- #else /* HAVE_TERMIO */
- if(!(_raw_tchars.t_startc == -1 && _raw_tchars.t_stopc == -1)){
- _raw_tchars.t_startc = -1; /* Turn off ^S/^Q */
- _raw_tchars.t_stopc = -1;
- (void) ioctl(STDIN_FD, TIOCSETC, &_raw_tchars);
- }
- #endif
- #endif
- }
- }
- }
-
-
-
- /*----------------------------------------------------------------------
- Set up the tty driver to do LF->CR translation (UNIX)
-
- Args: state -- True to turn on translation, false to write raw LF's
-
- Result: none.
-
- ----*/
- void
- crlf_proc(state)
- int state;
- {
- if(_inraw){
- if(state){ /* turn ON NL->CR on output */
- #ifdef HAVE_TERMIOS
- if(!(_raw_tty.c_oflag & ONLCR)){
- _raw_tty.c_oflag |= ONLCR;
- tcsetattr (STDIN_FD, TCSADRAIN, &_raw_tty);
- }
- #else
- #ifdef HAVE_TERMIO
- if(!(_raw_tty.c_oflag & ONLCR)){
- _raw_tty.c_oflag |= ONLCR;
- (void) ioctl(STDIN_FD, TCSETAW, &_raw_tty);
- }
- #else /* HAVE_TERMIO */
- if(!(_raw_tty.sg_flags & CRMOD)){
- _raw_tty.sg_flags |= CRMOD;
- (void) ioctl(STDIN_FD, TIOCSETP, &_raw_tty);
- }
- #endif
- #endif
- }
- else{ /* turn OFF NL-CR on output */
- #ifdef HAVE_TERMIOS
- if(_raw_tty.c_oflag & ONLCR){
- _raw_tty.c_oflag &= ~ONLCR;
- tcsetattr (STDIN_FD, TCSADRAIN, &_raw_tty);
- }
- #else
- #ifdef HAVE_TERMIO
- if(_raw_tty.c_oflag & ONLCR){
- _raw_tty.c_oflag &= ~ONLCR;
- (void) ioctl(STDIN_FD, TCSETAW, &_raw_tty);
- }
- #else /* HAVE_TERMIO */
- if(_raw_tty.sg_flags & CRMOD){
- _raw_tty.sg_flags &= ~CRMOD;
- (void) ioctl(STDIN_FD, TIOCSETP, &_raw_tty);
- }
- #endif
- #endif
- }
- }
- }
-
-
- /*----------------------------------------------------------------------
- Set up the tty driver to hanle interrupt char (UNIX)
-
- Args: state -- True to turn on interrupt char, false to not
-
- Result: tty driver that'll send us SIGINT or not
-
- ----*/
- void
- intr_proc(state)
- int state;
- {
- if(_inraw){
- if(state){
- #ifdef HAVE_TERMIOS
- _raw_tty.c_lflag |= ISIG; /* enable signals */
- _raw_tty.c_cc[VINTR] = ctrl('C');
- tcsetattr(STDIN_FD, TCSADRAIN, &_raw_tty);
- #else
- #ifdef HAVE_TERMIO
- _raw_tty.c_lflag |= ISIG; /* enable signals */
- _raw_tty.c_cc[VINTR] = ctrl('C');
- (void)ioctl(STDIN_FD, TCSETAW, &_raw_tty);
- #else
- _raw_tchars.t_intrc = ctrl('C');
- (void)ioctl(STDIN_FD, TIOCSETC, &_raw_tchars);
- #endif /* HAVE_TERMIO */
- #endif /* HAVE_TERMIOS */
- }
- else{
- #ifdef HAVE_TERMIOS
- _raw_tty.c_lflag &= ~ISIG; /* disable signals */
- _raw_tty.c_cc[VINTR] = 0;
- tcsetattr(STDIN_FD, TCSADRAIN, &_raw_tty);
- #else
- #ifdef HAVE_TERMIO
- _raw_tty.c_lflag &= ~ISIG; /* disable signals */
- _raw_tty.c_cc[VINTR] = 0;
- (void)ioctl(STDIN_FD, TCSETAW, &_raw_tty);
- #else /* HAVE_TERMIO */
- _raw_tchars.t_intrc = -1;
- (void)ioctl(STDIN_FD, TIOCSETC, &_raw_tchars);
- #endif /* HAVE_TERMIO */
- #endif /* HAVE_TERMIOS */
- }
- }
- }
-
-
- #ifdef RESIZING
- jmp_buf winch_state;
- int winch_occured = 0;
- int ready_for_winch = 0;
- #endif
-
- /*----------------------------------------------------------------------
- This checks whether or not a character (UNIX)
- is ready to be read, or it times out.
-
- Args: time_out -- number of seconds before it will timeout
-
- Result: Returns a NO_OP_IDLE or a NO_OP_COMMAND if the timeout expires
- before input is available, or a KEY_RESIZE if a resize event
- occurs, or READY_TO_READ if input is available before the timeout.
- ----*/
- int
- check_for_timeout(time_out)
- int time_out;
- {
- #ifdef USE_POLL
- struct pollfd pollfd;
- #else
- struct timeval tmo;
- fd_set readfds, errfds;
- #endif
- int res;
- unsigned char c;
-
- fflush(stdout);
-
- #ifdef RESIZING
- if(winch_occured || setjmp(winch_state) != 0) {
- ready_for_winch = 0;
- fix_windsize(ps_global);
- #ifdef POSIX_SIGNALS
- /*
- * Need to unblock signal after longjmp from handler, because
- * signal is normally unblocked upon routine exit from the handler.
- */
- if(!winch_occured)
- sigrelse(SIGWINCH);
- #endif
- winch_occured = 0;
- return(KEY_RESIZE);
- } else {
- ready_for_winch = 1;
- }
- #endif /* RESIZING */
-
- if(time_out > 0) {
- /* Check to see if there's bytes to read with a timeout */
- #ifdef USE_POLL
- pollfd.fd = STDIN_FD;
- pollfd.events = POLLIN;
- dprint(9,(debugfile,"poll event %d, timeout %d\n", pollfd.events,
- time_out));
- res = poll (&pollfd, 1, time_out * 1000);
- dprint(9, (debugfile, "poll on tty returned %d, events %d\n",
- res, pollfd.revents));
- #else
- FD_ZERO(&readfds);
- FD_ZERO(&errfds);
- FD_SET(STDIN_FD, &readfds);
- FD_SET(STDIN_FD, &errfds);
- tmo.tv_sec = time_out;
- tmo.tv_usec = 0;
-
- dprint(9, (debugfile,"Select readfds:%d timeval:%d,%d\n", readfds,
- tmo.tv_sec,tmo.tv_usec));
-
- res = select(STDIN_FD+1, &readfds, 0, &errfds, &tmo);
-
- dprint(9, (debugfile, "Select on tty returned %d\n", res));
- #endif
-
- if(res < 0) {
- if(errno == EINTR) {
- #ifdef RESIZING
- ready_for_winch = 0;
- #endif
- return(NO_OP_COMMAND);
- }
- panic1("Select error: %s\n", error_description(errno));
- }
-
- if(res == 0) { /* the select timed out */
- if(getppid() == 1){
- dprint(1, (debugfile,
- "\n\n** Parent found to be init!?!\n\n"));
- read_bail();
- /* NO RETURN */
- }
-
- #ifdef RESIZING
- ready_for_winch = 0;
- #endif
- return(time_out > 25 ? NO_OP_IDLE: NO_OP_COMMAND);
- }
- }
-
- #ifdef RESIZING
- ready_for_winch = 0;
- #endif
-
- return(READY_TO_READ);
- }
-
-
- /*----------------------------------------------------------------------
- Lowest level read command. This reads one character. (UNIX)
-
- Result: Returns the single character read or a NO_OP_COMMAND if the
- read was interrupted.
- ----*/
- int
- read_a_char()
- {
- int res;
- unsigned char c;
-
- res = read(STDIN_FD, &c, 1);
-
- if(res <= 0) {
- /*
- * Error reading from terminal!
- * The only acceptable failure is being interrupted. If so,
- * return a value indicating such...
- */
- if(res < 0 && errno == EINTR){
- dprint(2, (debugfile, "read_a_char interrupted\n"));
- RETURN_CH(NO_OP_COMMAND);
- }
-
- /*
- * Else we read EOF or otherwise encountered some catastrophic
- * error. Treat it like SIGHUP (i.e., clean up and exit).
- */
- dprint(1, (debugfile, "\n\n** Error reading from tty : %s\n\n",
- (res == 0) ? "EOF" : error_description(errno)));
-
- read_bail();
- /* NO RETURN */
- }
-
- dprint(9, (debugfile, "read_a_char return '\\%03o'\n", (int)c));
- RETURN_CH((int)c);
- }
-
-
- /*----------------------------------------------------------------------
- Simple version of read_a_char without the protection against
- errors found there. That's ok because kbseq will always return
- after only a few characters and the rare error will be noticed
- on the next call to read_a_char.
-
- Result: Returns the single character read or a NO_OP_COMMAND on error.
- ----*/
- int
- getchar_for_kbseq()
- {
- unsigned char c;
-
- if(read(STDIN_FD, &c, 1) <= 0)
- RETURN_CH(NO_OP_COMMAND);
- else
- RETURN_CH((int)c);
- }
-
-
- /*----------------------------------------------------------------------
- Read input characters with lots of processing for arrow keys and such (UNIX)
-
- Args: time_out -- The timeout to for the reads
-
- Result: returns the character read. Possible special chars.
-
- This deals with function and arrow keys as well.
-
- The idea is that this routine handles all escape codes so it done in
- only one place. Especially so the back arrow key can work when entering
- things on a line. Also so all function keys can be disabled and not
- cause weird things to happen.
- ---*/
- int
- read_char(time_out)
- int time_out;
- {
- int ch, status, cc;
-
- /* Get input from initial-keystrokes */
- if(process_config_input(&ch))
- return(ch);
-
- /*
- * We only check for timeouts at the start of read_char, not in the
- * middle of escape sequences.
- */
- ch = check_for_timeout(time_out);
- if(ch == NO_OP_IDLE || ch == NO_OP_COMMAND || ch == KEY_RESIZE)
- goto done;
-
- switch(status = kbseq(ps_global->kbesc, getchar_for_kbseq, &ch)){
- case KEY_DOUBLE_ESC:
- /*
- * Special hack to get around comm devices eating control characters.
- */
- ch = read_a_char();
- if(ch == NO_OP_COMMAND) /* user typed ESC ESC, then stopped */
- goto done;
-
- ch &= 0x7f;
- if(isdigit(ch)){
- int n = 0, i = ch - '0';
-
- if(!strchr("012", ch))
- goto done; /* bogus literal char value */
-
- while(n++ < 2){
- ch = read_a_char();
- if(ch == NO_OP_COMMAND || !isdigit(ch &= 0x7f)
- || (n == 1 && i == 2 && ch > '5'))
- goto done; /* bogus literal char value */
- /* remember Horner? */
- i = (i * 10) + (ch - '0');
- }
-
- ch = i;
- }
- else{
- if(islower(ch)) /* canonicalize if alpha */
- ch = toupper(ch);
-
- ch = (isalpha(ch) || ch == '@' || (ch >= '[' && ch <= '_'))
- ? ctrl(ch) : ch;
- }
-
- goto done;
-
- #ifdef MOUSE
- case KEY_XTERM_MOUSE:
- if(mouseexist()){
- /*
- * special hack to get mouse events from an xterm.
- * Get the details, then pass it past the keymenu event
- * handler, and then to the installed handler if there
- * is one...
- */
- static int down = 0;
- int button, x, y;
- unsigned cmd;
-
- clear_cursor_pos();
- ch = read_a_char();
- if(ch == NO_OP_COMMAND)
- goto done;
-
- button = ch & 0x03;
-
- ch = read_a_char();
- if(ch == NO_OP_COMMAND)
- goto done;
-
- x = ch - '!';
-
- ch = read_a_char();
- if(ch == NO_OP_COMMAND)
- goto done;
-
- y = ch - '!';
-
- ch = NO_OP_COMMAND;
- if(button == 0){ /* xterm button 1 down */
- down = 1;
- if(checkmouse(&cmd, 1, x, y))
- ch = (int)cmd;
- }
- else if (down && button == 3){
- down = 0;
- if(checkmouse(&cmd, 0, x, y))
- ch = (int)cmd;
- }
-
- goto done;
- }
-
- break;
- #endif /* MOUSE */
-
- case KEY_UP :
- case KEY_DOWN :
- case KEY_RIGHT :
- case KEY_LEFT :
- case KEY_PGUP :
- case KEY_PGDN :
- case KEY_HOME :
- case KEY_END :
- case KEY_DEL :
- case PF1 :
- case PF2 :
- case PF3 :
- case PF4 :
- case PF5 :
- case PF6 :
- case PF7 :
- case PF8 :
- case PF9 :
- case PF10 :
- case PF11 :
- case PF12 :
- dprint(9, (debugfile, "Read char returning: %d %s\n",
- status, pretty_command(status)));
- return(status);
-
- case KEY_SWALLOW_Z:
- status = KEY_JUNK;
- case KEY_SWAL_UP:
- case KEY_SWAL_DOWN:
- case KEY_SWAL_LEFT:
- case KEY_SWAL_RIGHT:
- for(cc = 0; cc != 'z' && cc != '~';)
- cc = read_a_char() & 0x7f;
-
- dprint(9, (debugfile, "Read char returning: %d %s\n",
- status, pretty_command(status)));
- return(status);
-
- case KEY_KERMIT:
- for(cc = 0; cc != '\033' || (read_a_char() & 0x7f) != '\\';)
- cc = read_a_char() & 0x7f;
-
- ch = KEY_JUNK;
- goto done;
-
- case BADESC:
- ch = KEY_JUNK;
- goto done;
-
- case 0: /* regular character */
- default:
- /*
- * we used to strip (ch &= 0x7f;), but this seems much cleaner
- * in the face of line noise and has the benefit of making it
- * tougher to emit mistakenly labeled MIME...
- */
- if((ch & 0x80) && (!ps_global->VAR_CHAR_SET
- || !strucmp(ps_global->VAR_CHAR_SET, "US-ASCII"))){
- dprint(9, (debugfile, "Read char returning: %d %s\n",
- status, pretty_command(status)));
- return(KEY_JUNK);
- }
- else if(ch == ctrl('Z')){
- dprint(9, (debugfile, "Read char calling do_suspend\n"));
- return(do_suspend(ps_global));
- }
-
-
- done:
- dprint(9, (debugfile, "Read char returning: %d %s\n",
- ch, pretty_command(ch)));
- return(ch);
- }
- }
-
-
- /*----------------------------------------------------------------------
- Reading input somehow failed and we need to shutdown now
-
- Args: none
-
- Result: pine exits
-
- ---*/
- void
- read_bail()
- {
- end_signals(1);
- if(ps_global->inbox_stream){
- if(ps_global->inbox_stream == ps_global->mail_stream)
- ps_global->mail_stream = NULL;
-
- if(!ps_global->inbox_stream->lock) /* shouldn't be... */
- mail_close(ps_global->inbox_stream);
- }
-
- if(ps_global->mail_stream && !ps_global->mail_stream->lock)
- mail_close(ps_global->mail_stream);
-
- end_keyboard(F_ON(F_USE_FK,ps_global));
- end_tty_driver(ps_global);
- if(filter_data_file(0))
- unlink(filter_data_file(0));
-
- exit(0);
- }
-
-
- extern char term_name[]; /* term_name from ttyout.c-- affect keyboard*/
- /* -------------------------------------------------------------------
- Set up the keyboard -- usually enable some function keys (UNIX)
-
- Args: struct pine
-
- So far all we do here is turn on keypad mode for certain terminals
-
- Hack for NCSA telnet on an IBM PC to put the keypad in the right mode.
- This is the same for a vtXXX terminal or [zh][12]9's which we have
- a lot of at UW
- ----*/
- void
- init_keyboard(use_fkeys)
- int use_fkeys;
- {
- if(use_fkeys && (!strucmp(term_name,"vt102")
- || !strucmp(term_name,"vt100")))
- printf("\033\133\071\071\150");
- }
-
-
-
- /*----------------------------------------------------------------------
- Clear keyboard, usually disable some function keys (UNIX)
-
- Args: pine state (terminal type)
-
- Result: keyboard state reset
- ----*/
- void
- end_keyboard(use_fkeys)
- int use_fkeys;
- {
- if(use_fkeys && (!strcmp(term_name, "vt102")
- || !strcmp(term_name, "vt100"))){
- printf("\033\133\071\071\154");
- fflush(stdout);
- }
- }
-
-
- /*----------------------------------------------------------------------
- Discard any pending input characters (UNIX)
-
- Args: none
-
- Result: pending input buffer flushed
- ----*/
- void
- flush_input()
- {
- #ifdef HAVE_TERMIOS
- tcflush(STDIN_FD, TCIFLUSH);
- #else
- #ifdef HAVE_TERMIO
- ioctl(STDIN_FD, TCFLSH, 0);
- #else
- #ifdef TIOCFLUSH
- #ifdef FREAD
- int i = FREAD;
- #else
- int i = 1;
- #endif
-
- ioctl(STDIN_FD, TIOCFLUSH, &i);
- #else
- #endif /* TIOCFLUSH */
- #endif /* HAVE_TERMIO */
- #endif /* HAVE_TERMIOS */
- }
-
-
- #else
- /*
- * DOS && OS/2 specific code.
- * Middle of giant switch between UNIX and DOS/OS2 input drivers
- */
-
-
- #ifdef OS2
- #define INCL_BASE
- #define INCL_DOS
- #define INCL_VIO
- #define INCL_KBD
- #define INCL_NOPM
- #include <os2.h>
- #undef ADDRESS
- #endif
-
- #include "headers.h"
-
-
- /*
- * Internal prototypes
- */
- void line_paint PROTO((int, int *));
- int process_config_input PROTO((int *));
-
-
-
- #if !(defined(WIN32) || defined(OS2))
- #include <dos.h>
- #include <bios.h>
- #endif
-
- /* global to tell us if we have an enhanced keyboard! */
- static int enhanced = 0;
- /* global function to execute while waiting for character input */
- void (*while_waiting)() = NULL;
-
- #ifdef _WINDOWS
- /* global to tell us if the window was resized. */
- static int DidResize = FALSE;
-
-
- /*----------------------------------------------------------------------
- Flag the fact the window has resized.
- */
- int
- pine_window_resize_callback ()
- {
- DidResize = TRUE;
- }
- #endif
-
-
-
- /*----------------------------------------------------------------------
- Initialize the tty driver to do single char I/O and whatever else (DOS)
-
- Input: struct pine
-
- Result: tty driver is put in raw mode
- ----------------------------------------------------------------------*/
- init_tty_driver(pine)
- struct pine *pine;
- {
- #ifdef _WINDOWS
- mswin_setresizecallback (pine_window_resize_callback);
- init_mouse (); /* always a mouse under windows? */
- #else
- #ifdef OS2
- enhanced = 1;
- #else
- /* detect enhanced keyboard */
- enhanced = enhanced_keybrd(); /* are there extra keys? */
- #endif
- #endif
- pine = pine; /* Get rid of unused parm warning */
- return(Raw(1));
- }
-
-
-
- /*----------------------------------------------------------------------
- End use of the tty, put it back into it's normal mode (DOS)
-
- Input: struct pine
-
- Result: tty driver mode change
- ----------------------------------------------------------------------*/
- void
- end_tty_driver(pine)
- struct pine *pine;
- {
- dprint(2, (debugfile, "about to end_tty_driver\n"));
- #ifdef _WINDOWS
- mswin_clearresizecallback (pine_window_resize_callback);
- #endif
- }
-
- /*----------------------------------------------------------------------
- translate IBM Keyboard Extended Functions to things pine understands.
- More work can be done to make things like Home, PageUp and PageDown work.
-
- /*
- * extended_code - return special key definition
- */
- extended_code(kc)
- unsigned kc;
- {
- switch(kc){
- #ifdef _WINDOWS
- case MSWIN_KEY_F1: return(PF1);
- case MSWIN_KEY_F2: return(PF2);
- case MSWIN_KEY_F3: return(PF3);
- case MSWIN_KEY_F4: return(PF4);
- case MSWIN_KEY_F5: return(PF5);
- case MSWIN_KEY_F6: return(PF6);
- case MSWIN_KEY_F7: return(PF7);
- case MSWIN_KEY_F8: return(PF8);
- case MSWIN_KEY_F9: return(PF9);
- case MSWIN_KEY_F10: return(PF10);
- case MSWIN_KEY_F11: return(PF11);
- case MSWIN_KEY_F12: return(PF12);
-
- case MSWIN_KEY_UP: return(KEY_UP);
- case MSWIN_KEY_DOWN: return(KEY_DOWN);
- case MSWIN_KEY_LEFT: return(KEY_LEFT);
- case MSWIN_KEY_RIGHT: return(KEY_RIGHT);
- case MSWIN_KEY_HOME: return(KEY_HOME);
- case MSWIN_KEY_END: return(KEY_END);
- case MSWIN_KEY_SCROLLUPPAGE:
- case MSWIN_KEY_PREVPAGE: return(KEY_PGUP);
- case MSWIN_KEY_SCROLLDOWNPAGE:
- case MSWIN_KEY_NEXTPAGE: return(KEY_PGDN);
- case MSWIN_KEY_DELETE: return(KEY_DEL);
- case MSWIN_KEY_SCROLLUPLINE: return (KEY_SCRLUPL);
- case MSWIN_KEY_SCROLLDOWNLINE: return (KEY_SCRLDNL);
- case MSWIN_KEY_SCROLLTO: return (KEY_SCRLTO);
-
- case MSWIN_KEY_NODATA: return (NO_OP_COMMAND);
- #else
- case 0x3b00 : return(PF1);
- case 0x3c00 : return(PF2);
- case 0x3d00 : return(PF3);
- case 0x3e00 : return(PF4);
- case 0x3f00 : return(PF5);
- case 0x4000 : return(PF6);
- case 0x4100 : return(PF7);
- case 0x4200 : return(PF8);
- case 0x4300 : return(PF9);
- case 0x4400 : return(PF10);
- case 0x8500 : return(PF11);
- case 0x8600 : return(PF12);
-
- case 0x4800 : return(KEY_UP);
- case 0x5000 : return(KEY_DOWN);
- case 0x4b00 : return(KEY_LEFT);
- case 0x4d00 : return(KEY_RIGHT);
- case 0x4700 : return(KEY_HOME);
- case 0x4f00 : return(KEY_END);
- case 0x4900 : return(KEY_PGUP);
- case 0x5100 : return(KEY_PGDN);
- case 0x5300 : return(KEY_DEL);
- case 0x48e0 : return(KEY_UP); /* grey key version */
- case 0x50e0 : return(KEY_DOWN); /* grey key version */
- case 0x4be0 : return(KEY_LEFT); /* grey key version */
- case 0x4de0 : return(KEY_RIGHT); /* grey key version */
- case 0x47e0 : return(KEY_HOME); /* grey key version */
- case 0x4fe0 : return(KEY_END); /* grey key version */
- case 0x49e0 : return(KEY_PGUP); /* grey key version */
- case 0x51e0 : return(KEY_PGDN); /* grey key version */
- case 0x53e0 : return(KEY_DEL); /* grey key version */
- #endif
- default : return(NO_OP_COMMAND);
- }
- }
-
-
-
- /*----------------------------------------------------------------------
- Read input characters with lots of processing for arrow keys and such (DOS)
-
- Input: none
-
- Result: returns the character read. Possible special chars defined h file
-
-
- This deals with function and arrow keys as well.
- It returns ^T for up , ^U for down, ^V for forward and ^W for back.
- These are just sort of arbitrarily picked and might be changed.
- They are defined in defs.h. Didn't want to use 8 bit chars because
- the values are signed chars, though it ought to work with negative
- values.
-
- The idea is that this routine handles all escape codes so it done in
- only one place. Especially so the back arrow key can work when entering
- things on a line. Also so all function keys can be broken and not
- cause weird things to happen.
- ----------------------------------------------------------------------*/
-
- int
- read_char(tm)
- int tm;
- {
- unsigned ch = 0;
- long timein;
- #ifndef _WINDOWS
- unsigned intrupt = 0;
- extern int win_multiplex();
- #endif
-
- if(process_config_input((int *) &ch))
- RETURN_CH(ch);
-
- #ifdef _WINDOWS
- if (DidResize) {
- DidResize = FALSE;
- RETURN_CH (get_windsize (ps_global->ttyo));
- }
- #endif
-
- #ifdef OS2
- vidUpdate();
- #endif
- #ifdef MOUSE
- mouseon();
- #endif
-
- if(tm){
- timein = time(0L);
- #ifdef _WINDOWS
- /* mswin_charavail() Yeilds control to other window apps. */
- while (!mswin_charavail()) {
- #else
- #ifdef OS2
- while (!kbd_ready()) {
- #else
- while(!_bios_keybrd(enhanced ? _NKEYBRD_READY : _KEYBRD_READY)){
- #endif
- #endif
- if(time(0L) >= timein+tm){
- ch = NO_OP_COMMAND;
- goto gotone;
- }
- #ifdef _WINDOWS
- if (DidResize) {
- DidResize = FALSE;
- RETURN_CH( get_windsize (ps_global->ttyo));
- }
- #endif
- #ifdef MOUSE
- if(checkmouse(&ch,0,0,0))
- goto gotone;
- #endif
- if(while_waiting)
- (*while_waiting)();
-
- #ifndef _WINDOWS
- /*
- * the number "30" was not reached via experimentation
- * or scientific analysis of any kind.
- */
- if(((intrupt++) % 30) == 0) /* surrender CPU to windows */
- win_multiplex();
- #endif
- }
- }
-
- #ifdef _WINDOWS
- ch = mswin_getc_fast();
- #else
- #ifdef OS2
- ch = kbd_getkey();
- #else
- ch = _bios_keybrd(enhanced ? _NKEYBRD_READ : _KEYBRD_READ);
- #endif
- #endif
-
- gotone:
- #if defined(MOUSE)
- mouseoff();
-
- /* More obtuse key mapping. If it is a mouse event, the return
- * may be KEY_MOUSE, which indicates to the upper layer that it
- * is a mouse event. Return it here to avoid the code that
- * follows which would do a (ch & 0xff).
- */
- if (ch == KEY_MOUSE)
- RETURN_CH(ch);
- #endif
-
- /*
- * WARNING: Hack notice.
- * the mouse interaction complicates this expression a bit as
- * if function key mode is set, PFn values are setup for return
- * by the mouse event catcher. For now, just special case them
- * since they don't conflict with any of the DOS special keys.
- */
- #ifdef _WINDOWS
-
- if (ch >= MSWIN_RANGE_START && ch <= MSWIN_RANGE_END)
- RETURN_CH (extended_code (ch));
-
- RETURN_CH (ch&0xff);
- #else /* DOS */
- if((ch & 0xff) == ctrl('Z'))
- RETURN_CH(do_suspend(ps_global));
-
- RETURN_CH((ch >= PF1 && ch <= PF12)
- ? ch
- : ((ch&0xff) && ((ch&0xff) != 0xe0))
- ? (ch&0xff)
- : extended_code(ch));
- #endif
- }
-
- #ifdef OS2
- static KBDINFO initialKbdInfo;
- #endif
-
- /* -------------------------------------------------------------------
- Set up the keyboard -- usually enable some function keys (DOS)
-
- Input: struct pine (terminal type)
-
- Result: keyboard set up
-
- -----------------------------------------------------------------------*/
- void
- init_keyboard(use_fkeys)
- int use_fkeys;
- {
- #ifdef OS2
- KBDINFO kbdInfo;
- KbdGetStatus(&initialKbdInfo, 0);
- kbdInfo = initialKbdInfo;
- kbdInfo.fsMask &= ~(0x0001|0x0008|0x0100); /* echo cooked off */
- kbdInfo.fsMask |= (0x002|0x004|0x0100); /* noecho,raw,shiftrpt on */
- KbdSetStatus(&kbdInfo, 0);
- #endif
- }
-
-
-
- /*----------------------------------------------------------------------
- Clear keyboard, usually disable some function keys (DOS)
-
- Input: pine state (terminal type)
-
- Result: keyboard state reset
- ----------------------------------------------------------------------*/
- /* BUG shouldn't have to check for pine != NULL */
- void
- end_keyboard(use_fkeys)
- int use_fkeys;
- {
- #ifdef OS2
- KbdSetStatus(&initialKbdInfo, 0);
- #endif
- }
-
-
-
- /*----------------------------------------------------------------------
- Discard any pending input characters (DOS)
-
- Args: none
-
- Result: pending input buffer flushed
- ----*/
- void
- flush_input()
- {
- #ifdef _WINDOWS
- while (mswin_charavail ())
- (void) mswin_getc ();
- #else
- #ifdef OS2
- kbd_flush();
- #else
- while(_bios_keybrd(enhanced ? _NKEYBRD_READY : _KEYBRD_READY))
- (void) _bios_keybrd(enhanced ? _NKEYBRD_READ : _KEYBRD_READ);
- #endif
- #endif
- }
-
-
- /*----------------------------------------------------------------------
- Actually set up the tty driver (DOS)
-
- Args: state -- which state to put it in. 1 means go into raw, 0 out of
-
- Result: returns 0 if successful and -1 if not.
- ----*/
-
- Raw(state)
- int state;
- {
- /* of course, DOS never runs at low speed!!! */
- ps_global->low_speed = 0;
- return(0);
- }
-
-
- /*----------------------------------------------------------------------
- Set up the tty driver to use XON/XOFF flow control (DOS)
-
- Args: state -- True to make sure XON/XOFF turned on, FALSE default state
-
- Result: none.
- ----*/
- void
- xonxoff_proc(state)
- int state;
- {
- return; /* no op */
- }
-
-
- /*----------------------------------------------------------------------
- Set up the tty driver to do LF->CR translation (DOS)
-
- Args: state -- True to turn on translation, false to write raw LF's
-
- Result: none.
-
- ----*/
- void
- crlf_proc(state)
- int state;
- {
- return; /* no op */
- }
-
-
- /*----------------------------------------------------------------------
- Set up the tty driver to hanle interrupt char (DOS)
-
- Args: state -- True to turn on interrupt char, false to not
-
- Result: tty driver that'll send us SIGINT or not
-
- ----*/
- void
- intr_proc(state)
- int state;
- {
- return; /* no op */
- }
- #endif /* DOS End of giant switch between UNX and DOS input drivers */
-
-
- /*----------------------------------------------------------------------
- Read a character from keyboard with timeout
- Input: none
-
- Result: Returns command read via read_char
- Times out and returns a null command every so often
-
- Calculates the timeout for the read, and does a few other house keeping
- things. The duration of the timeout is set in pine.c.
- ----------------------------------------------------------------------*/
- int
- read_command()
- {
- int ch, tm = 0;
- long dtime;
-
- cancel_busy_alarm(-1);
- tm = (messages_queued(&dtime) > 1) ? (int)dtime : timeout;
-
- ch = read_char(tm);
- dprint(9, (debugfile, "Read command returning: %d %s\n", ch,
- pretty_command(ch)));
- if(ch != NO_OP_COMMAND && ch != NO_OP_IDLE && ch != KEY_RESIZE)
- zero_new_mail_count();
-
- return(ch);
- }
-
-
-
-
- /*
- *
- */
- static struct display_line {
- int row, col; /* where display starts */
- int dlen; /* length of display line */
- char *dl; /* line on display */
- char *vl; /* virtual line */
- int vlen; /* length of virtual line */
- int vused; /* length of virtual line in use */
- int vbase; /* first virtual char on display */
- } dline;
-
-
-
- static struct key oe_keys[] =
- {{"^G","Help",KS_SCREENHELP}, {"^C","Cancel",KS_NONE},
- {"^T","xxx",KS_NONE}, {"Ret","Accept",KS_NONE},
- {NULL,NULL,KS_NONE}, {NULL,NULL,KS_NONE},
- {NULL,NULL,KS_NONE}, {NULL,NULL,KS_NONE},
- {NULL,NULL,KS_NONE}, {NULL,NULL,KS_NONE},
- {NULL,NULL,KS_NONE}, {NULL,NULL,KS_NONE}};
- static struct key_menu oe_keymenu =
- {sizeof(oe_keys)/(sizeof(oe_keys[0])*12), 0, 0,0,0,0, oe_keys};
- #define OE_HELP_KEY 0
- #define OE_CANCEL_KEY 1
- #define OE_CTRL_T_KEY 2
- #define OE_ENTER_KEY 3
-
-
- /*----------------------------------------------------------------------
- Prompt user for a string in status line with various options
-
- Args: string -- the buffer result is returned in, and original string (if
- any) is passed in.
- y_base -- y position on screen to start on. 0,0 is upper left
- negative numbers start from bottom
- x_base -- column position on screen to start on. 0,0 is upper left
- field_len -- Maximum length of string to accept
- append_current -- flag indicating string should not be truncated before
- accepting input
- passwd -- a pass word is being fetch. Don't echo on screen
- prompt -- The string to prompt with
- escape_list -- pointer to array of ESCKEY_S's. input chars matching
- those in list return value from list.
- help -- Arrary of strings for help text in bottom screen lines
- flags -- flags
-
- Result: editing input string
- returns -1 unexpected errors
- returns 0 normal entry typed (editing and return or PF2)
- returns 1 typed ^C or PF2 (cancel)
- returns 3 typed ^G or PF1 (help)
- returns 4 typed ^L for a screen redraw
-
- WARNING: Care is required with regard to the escape_list processing.
- The passed array is terminated with an entry that has ch = -1.
- Function key labels and key strokes need to be setup externally!
- Traditionally, a return value of 2 is used for ^T escapes.
-
- Unless in escape_list, tabs are trapped by isprint().
- This allows near full weemacs style editing in the line
- ^A beginning of line
- ^E End of line
- ^R Redraw line
- ^G Help
- ^F forward
- ^B backward
- ^D delete
- ----------------------------------------------------------------------*/
-
- optionally_enter(string, y_base, x_base, field_len, append_current, passwd,
- prompt, escape_list, help, flags)
- char *string, *prompt;
- ESCKEY_S *escape_list;
- HelpType help;
- int x_base, y_base, field_len, append_current, passwd;
- unsigned flags;
- {
- register char *s2;
- register int field_pos;
- int i, j, return_v, cols, ch, prompt_len, too_thin,
- real_y_base, cursor_moved, km_popped;
- char *saved_original = NULL, *k, *kb;
- char *kill_buffer = NULL;
- char **help_text;
- int fkey_table[12];
- struct key_menu *km;
- bitmap_t bitmap;
-
- dprint(5, (debugfile, "=== optionally_enter called ===\n"));
- dprint(9, (debugfile, "string:\"%s\" y:%d x:%d length: %d append: %d\n",
- string, x_base, y_base, field_len, append_current));
- dprint(9, (debugfile, "passwd:%d prompt:\"%s\" label:\"%s\"\n",
- passwd, prompt, (escape_list && escape_list[0].ch != -1)
- ? escape_list[0].label: ""));
-
- #ifdef _WINDOWS
- if (mswin_usedialog ()) {
- MDlgButton button_list[12];
- int b;
- int i;
-
- memset (&button_list, 0, sizeof (MDlgButton) * 12);
- b = 0;
- for (i = 0; escape_list && escape_list[i].ch != -1 && i < 11; ++i) {
- if (escape_list[i].name != NULL
- && escape_list[i].ch > 0 && escape_list[i].ch < 256) {
- button_list[b].ch = escape_list[i].ch;
- button_list[b].rval = escape_list[i].rval;
- button_list[b].name = escape_list[i].name;
- button_list[b].label = escape_list[i].label;
- ++b;
- }
- }
- button_list[b].ch = -1;
-
-
- help_text = get_help_text (help, NULL);
- return_v = mswin_dialog (prompt, string, field_len,
- append_current, passwd, button_list, help_text, flags);
- if (help_text != NULL)
- free_help_text (help_text);
- return (return_v);
- }
- #endif
-
- suspend_busy_alarm();
- cols = ps_global->ttyo->screen_cols;
- prompt_len = strlen(prompt);
- too_thin = 0;
- km_popped = 0;
- if(y_base > 0) {
- real_y_base = y_base;
- } else {
- real_y_base= y_base + ps_global->ttyo->screen_rows;
- if(real_y_base < 2)
- real_y_base = ps_global->ttyo->screen_rows;
- }
-
- flush_ordered_messages();
- mark_status_dirty();
- if(append_current) /* save a copy in case of cancel */
- saved_original = cpystr(string);
-
- /*
- * build the function key mapping table, skipping predefined keys...
- */
- memset(fkey_table, NO_OP_COMMAND, 12 * sizeof(int));
- for(i = 0, j = 0; escape_list && escape_list[i].ch != -1 && i+j < 12; i++){
- if(i+j == OE_HELP_KEY)
- j++;
-
- if(i+j == OE_CANCEL_KEY)
- j++;
-
- if(i+j == OE_ENTER_KEY)
- j++;
-
- fkey_table[i+j] = escape_list[i].ch;
- }
-
- #if defined(HELPFILE)
- help_text = (help != NO_HELP) ? get_help_text(help, NULL) : (char **)NULL;
- #else
- help_text = help;
- #endif
- if(help_text){ /*---- Show help text -----*/
- int width = ps_global->ttyo->screen_cols - x_base;
-
- if(FOOTER_ROWS(ps_global) == 1){
- km_popped++;
- FOOTER_ROWS(ps_global) = 3;
- clearfooter(ps_global);
-
- y_base = -3;
- real_y_base = y_base + ps_global->ttyo->screen_rows;
- }
-
- for(j = 0; j < 2 && help_text[j]; j++){
- MoveCursor(real_y_base + 1 + j, x_base);
- CleartoEOLN();
-
- if(width < strlen(help_text[j])){
- char *tmp = fs_get((width + 1) * sizeof(char));
- strncpy(tmp, help_text[j], width);
- tmp[width] = '\0';
- PutLine0(real_y_base + 1 + j, x_base, tmp);
- fs_give((void **)&tmp);
- }
- else
- PutLine0(real_y_base + 1 + j, x_base, help_text[j]);
- }
-
- #if defined(HELPFILE)
- free_help_text(help_text);
- #endif
-
- } else {
- clrbitmap(bitmap);
- clrbitmap((km = &oe_keymenu)->bitmap); /* force formatting */
- setbitn(OE_HELP_KEY, bitmap);
- setbitn(OE_ENTER_KEY, bitmap);
- if(!(flags & OE_DISALLOW_CANCEL))
- setbitn(OE_CANCEL_KEY, bitmap);
- setbitn(OE_CTRL_T_KEY, bitmap);
-
- /*---- Show the usual possible keys ----*/
- for(i=0,j=0; escape_list && escape_list[i].ch != -1 && i+j < 12; i++){
- if(i+j == OE_HELP_KEY)
- j++;
-
- if(i+j == OE_CANCEL_KEY)
- j++;
-
- if(i+j == OE_ENTER_KEY)
- j++;
-
- oe_keymenu.keys[i+j].label = escape_list[i].label;
- oe_keymenu.keys[i+j].name = escape_list[i].name;
- setbitn(i+j, bitmap);
- }
-
- for(i = i+j; i < 12; i++)
- if(!(i == OE_HELP_KEY || i == OE_ENTER_KEY || i == OE_CANCEL_KEY))
- oe_keymenu.keys[i].name = NULL;
-
- draw_keymenu(km, bitmap, cols, 1-FOOTER_ROWS(ps_global),
- 0, FirstMenu, 0);
- }
-
-
- StartInverse(); /* Always in inverse */
-
- /*
- * if display length isn't wide enough to support input,
- * shorten up the prompt...
- */
- if((dline.dlen = cols - (x_base + prompt_len + 1)) < 5){
- prompt_len += (dline.dlen - 5); /* adding negative numbers */
- prompt -= (dline.dlen - 5); /* subtracting negative numbers */
- dline.dlen = 5;
- }
-
- dline.dl = fs_get((size_t)dline.dlen + 1);
- memset((void *)dline.dl, 0, (size_t)(dline.dlen + 1) * sizeof(char));
- dline.row = real_y_base;
- dline.col = x_base + prompt_len;
- dline.vl = string;
- dline.vlen = --field_len; /* -1 for terminating NULL */
- dline.vbase = field_pos = 0;
-
- PutLine0(real_y_base, x_base, prompt);
- /* make sure passed in string is shorter than field_len */
- /* and adjust field_pos.. */
-
- while(append_current && field_pos < field_len && string[field_pos] != '\0')
- field_pos++;
-
- string[field_pos] = '\0';
- dline.vused = (int)(&string[field_pos] - string);
- line_paint(field_pos, &passwd);
-
- #ifdef _WINDOWS
- mswin_allowpaste(MSWIN_PASTE_LINE);
- #endif
-
- /*----------------------------------------------------------------------
- The main loop
-
- here field_pos is the position in the string.
- s always points to where we are in the string.
- loops until someone sets the return_v.
- ----------------------------------------------------------------------*/
- return_v = -10;
-
- while(return_v == -10) {
- /* Timeout 5 min to keep imap mail stream alive */
- ch = read_char(600);
-
- /*
- * Don't want to intercept all characters if typing in passwd.
- * We select an ad hoc set that we will catch and let the rest
- * through. We would have caught the set below in the big switch
- * but we skip the switch instead. Still catch things like ^K,
- * DELETE, ^C, RETURN.
- */
- if(passwd)
- switch(ch) {
- case ctrl('F'):
- case KEY_RIGHT:
- case ctrl('B'):
- case KEY_LEFT:
- case ctrl('U'):
- case ctrl('A'):
- case KEY_HOME:
- case ctrl('E'):
- case KEY_END:
- case TAB:
- goto ok_for_passwd;
- }
-
- if(too_thin && ch != KEY_RESIZE && ch != ctrl('Z'))
- goto bleep;
-
- switch(ch) {
-
- /*--------------- KEY RIGHT ---------------*/
- case ctrl('F'):
- case KEY_RIGHT:
- if(field_pos >= field_len || string[field_pos] == '\0')
- goto bleep;
-
- line_paint(++field_pos, &passwd);
- break;
-
- /*--------------- KEY LEFT ---------------*/
- case ctrl('B'):
- case KEY_LEFT:
- if(field_pos <= 0)
- goto bleep;
-
- line_paint(--field_pos, &passwd);
- break;
-
- /*-------------------- RETURN --------------------*/
- case PF4:
- if(F_OFF(F_USE_FK,ps_global)) goto bleep;
- case ctrl('J'):
- case ctrl('M'):
- return_v = 0;
- break;
-
- /*-------------------- Destructive backspace --------------------*/
- case '\177': /* DEL */
- case ctrl('H'):
- /* Try and do this with by telling the terminal to delete a
- a character. If that fails, then repaint the rest of the
- line, acheiving the same much less efficiently
- */
- if(field_pos <= 0) goto bleep;
- field_pos--;
- /* drop thru to pull line back ... */
-
- /*-------------------- Delete char --------------------*/
- case ctrl('D'):
- case KEY_DEL:
- if(field_pos >= field_len || !string[field_pos]) goto bleep;
-
- dline.vused--;
- for(s2 = &string[field_pos]; *s2 != '\0'; s2++)
- *s2 = s2[1];
-
- *s2 = '\0'; /* Copy last NULL */
- line_paint(field_pos, &passwd);
- break;
-
-
- /*--------------- Kill line -----------------*/
- case ctrl('K'):
- if(kill_buffer != NULL)
- fs_give((void **)&kill_buffer);
-
- kill_buffer = cpystr(string);
- string[0] = '\0';
- field_pos = 0;
- dline.vused = 0;
- line_paint(field_pos, &passwd);
- break;
-
- /*------------------- Undelete line --------------------*/
- case ctrl('U'):
- if(kill_buffer == NULL)
- goto bleep;
-
- /* Make string so it will fit */
- kb = cpystr(kill_buffer);
- dprint(2, (debugfile,
- "Undelete: %d %d\n", strlen(string), field_len));
- if(strlen(kb) + strlen(string) > field_len)
- kb[field_len - strlen(string)] = '\0';
- dprint(2, (debugfile,
- "Undelete: %d %d\n", field_len - strlen(string),
- strlen(kb)));
-
- if(string[field_pos] == '\0') {
- /*--- adding to the end of the string ----*/
- for(k = kb; *k; k++)
- string[field_pos++] = *k;
-
- string[field_pos] = '\0';
- } else {
- goto bleep;
- /* To lazy to do insert in middle of string now */
- }
-
- dline.vused = strlen(string);
- fs_give((void **)&kb);
- line_paint(field_pos, &passwd);
- break;
-
-
- /*-------------------- Interrupt --------------------*/
- case ctrl('C'): /* ^C */
- if(F_ON(F_USE_FK,ps_global) || flags & OE_DISALLOW_CANCEL)
- goto bleep;
-
- goto cancel;
- case PF2:
- if(F_OFF(F_USE_FK,ps_global) || flags & OE_DISALLOW_CANCEL)
- goto bleep;
-
- cancel:
- return_v = 1;
- if(saved_original)
- strcpy(string, saved_original);
-
- break;
-
-
- case ctrl('A'):
- case KEY_HOME:
- /*-------------------- Start of line -------------*/
- line_paint(field_pos = 0, &passwd);
- break;
-
-
- case ctrl('E'):
- case KEY_END:
- /*-------------------- End of line ---------------*/
- line_paint(field_pos = dline.vused, &passwd);
- break;
-
-
- /*-------------------- Help --------------------*/
- case ctrl('G') :
- case PF1:
- if(FOOTER_ROWS(ps_global) == 1 && km_popped == 0){
- km_popped++;
- FOOTER_ROWS(ps_global) = 3;
- clearfooter(ps_global);
- EndInverse();
- draw_keymenu(km, bitmap, cols, 1-FOOTER_ROWS(ps_global),
- 0, FirstMenu, 0);
- StartInverse();
- mark_keymenu_dirty();
- y_base = -3;
- dline.row = real_y_base = y_base + ps_global->ttyo->screen_rows;
- PutLine0(real_y_base, x_base, prompt);
- fs_resize((void **)&dline.dl, (size_t)dline.dlen + 1);
- memset((void *)dline.dl, 0, (size_t)(dline.dlen + 1));
- line_paint(field_pos, &passwd);
- break;
- }
-
- if(FOOTER_ROWS(ps_global) > 1){
- mark_keymenu_dirty();
- return_v = 3;
- }
- else
- goto bleep;
-
- break;
-
-
- /*-------- Misunderstood escape sequence? -------*/
- case NO_OP_COMMAND:
- continue;
-
-
- case NO_OP_IDLE:
- if(new_mail(0, 2, 0) < 0) /* Keep mail stream alive */
- break; /* no changes, get on with life */
- /* Else fall into redraw */
-
- /*-------------------- Redraw --------------------*/
- case ctrl('L'):
- /*---------------- re size ----------------*/
- case KEY_RESIZE:
-
- dline.row = real_y_base = y_base > 0 ? y_base :
- y_base + ps_global->ttyo->screen_rows;
- EndInverse();
- ClearScreen();
- redraw_titlebar();
- if(ps_global->redrawer != (void (*)())NULL)
- (*ps_global->redrawer)();
-
- redraw_keymenu();
- StartInverse();
-
- PutLine0(real_y_base, x_base, prompt);
- cols = ps_global->ttyo->screen_cols;
- too_thin = 0;
- if(cols < x_base + prompt_len + 4) {
- Writechar(BELL, 0);
- PutLine0(real_y_base, 0, "Screen's too thin. Ouch!");
- too_thin = 1;
- } else {
- dline.col = x_base + prompt_len;
- dline.dlen = cols - (x_base + prompt_len + 1);
- fs_resize((void **)&dline.dl, (size_t)dline.dlen + 1);
- memset((void *)dline.dl, 0, (size_t)(dline.dlen + 1));
- line_paint(field_pos, &passwd);
- }
- fflush(stdout);
-
- dprint(9, (debugfile,
- "optionally_enter RESIZE new_cols:%d too_thin: %d\n",
- cols, too_thin));
- break;
-
- case PF3 : /* input to potentially remap */
- case PF5 :
- case PF6 :
- case PF7 :
- case PF8 :
- case PF9 :
- case PF10 :
- case PF11 :
- case PF12 :
- if(F_ON(F_USE_FK,ps_global)
- && fkey_table[ch - PF1] != NO_OP_COMMAND)
- ch = fkey_table[ch - PF1]; /* remap function key input */
-
- default:
- if(escape_list){ /* in the escape key list? */
- for(j=0; escape_list[j].ch != -1; j++){
- if(escape_list[j].ch == ch){
- return_v = escape_list[j].rval;
- break;
- }
- }
-
- if(return_v != -10)
- break;
- }
-
- if(iscntrl(ch & 0x7f)){
- bleep:
- putc(BELL, stdout);
- continue;
- }
-
- ok_for_passwd:
- /*--- Insert a character -----*/
- if(dline.vused >= field_len)
- goto bleep;
-
- /*---- extending the length of the string ---*/
- for(s2 = &string[++dline.vused]; s2 - string > field_pos; s2--)
- *s2 = *(s2-1);
-
- string[field_pos++] = ch;
- line_paint(field_pos, &passwd);
-
- } /*---- End of switch on char ----*/
- }
-
- #ifdef _WINDOWS
- mswin_allowpaste(MSWIN_PASTE_DISABLE);
- #endif
- fs_give((void **)&dline.dl);
- if(saved_original)
- fs_give((void *)&saved_original);
-
- if(kill_buffer)
- fs_give((void **)&kill_buffer);
-
- removing_trailing_white_space(string);
- EndInverse();
- MoveCursor(real_y_base, x_base); /* Move the cursor to show we're done */
- fflush(stdout);
- resume_busy_alarm();
- if(km_popped){
- FOOTER_ROWS(ps_global) = 1;
- clearfooter(ps_global);
- ps_global->mangled_body = 1;
- }
-
- return(return_v);
- }
-
-
- /*
- * line_paint - where the real work of managing what is displayed gets done.
- * The passwd variable is overloaded: if non-zero, don't
- * output anything, else only blat blank chars across line
- * once and use this var to tell us we've already written the
- * line.
- */
- void
- line_paint(offset, passwd)
- int offset; /* current dot offset into line */
- int *passwd; /* flag to hide display of chars */
- {
- register char *pfp, *pbp;
- register char *vfp, *vbp;
- int extra = 0;
- #define DLEN (dline.vbase + dline.dlen)
-
- /*
- * for now just leave line blank, but maybe do '*' for each char later
- */
- if(*passwd){
- if(*passwd > 1)
- return;
- else
- *passwd == 2; /* only blat once */
-
- extra = 0;
- MoveCursor(dline.row, dline.col);
- while(extra++ < dline.dlen)
- Writechar(' ', 0);
-
- MoveCursor(dline.row, dline.col);
- return;
- }
-
- /* adjust right margin */
- while(offset >= DLEN + ((dline.vused > DLEN) ? -1 : 1))
- dline.vbase += dline.dlen/2;
-
- /* adjust left margin */
- while(offset < dline.vbase + ((dline.vbase) ? 2 : 0))
- dline.vbase = max(dline.vbase - (dline.dlen/2), 0);
-
- if(dline.vbase){ /* off screen cue left */
- vfp = &dline.vl[dline.vbase+1];
- pfp = &dline.dl[1];
- if(dline.dl[0] != '<'){
- MoveCursor(dline.row, dline.col);
- Writechar(dline.dl[0] = '<', 0);
- }
- }
- else{
- vfp = dline.vl;
- pfp = dline.dl;
- if(dline.dl[0] == '<'){
- MoveCursor(dline.row, dline.col);
- Writechar(dline.dl[0] = ' ', 0);
- }
- }
-
- if(dline.vused > DLEN){ /* off screen right... */
- vbp = vfp + (long)(dline.dlen-(dline.vbase ? 2 : 1));
- pbp = pfp + (long)(dline.dlen-(dline.vbase ? 2 : 1));
- if(pbp[1] != '>'){
- MoveCursor(dline.row, dline.col+dline.dlen);
- Writechar(pbp[1] = '>', 0);
- }
- }
- else{
- extra = dline.dlen - (dline.vused - dline.vbase);
- vbp = &dline.vl[max(0, dline.vused-1)];
- pbp = &dline.dl[dline.dlen];
- if(pbp[0] == '>'){
- MoveCursor(dline.row, dline.col+dline.dlen);
- Writechar(pbp[0] = ' ', 0);
- }
- }
-
- while(*pfp == *vfp && vfp < vbp) /* skip like chars */
- pfp++, vfp++;
-
- if(pfp == pbp && *pfp == *vfp){ /* nothing to paint! */
- MoveCursor(dline.row, dline.col + (offset - dline.vbase));
- return;
- }
-
- /* move backward thru like characters */
- if(extra){
- while(extra >= 0 && *pbp == ' ') /* back over spaces */
- extra--, pbp--;
-
- while(extra >= 0) /* paint new ones */
- pbp[-(extra--)] = ' ';
- }
-
- if((vbp - vfp) == (pbp - pfp)){ /* space there? */
- while((*pbp == *vbp) && pbp != pfp) /* skip like chars */
- pbp--, vbp--;
- }
-
- if(pfp != pbp || *pfp != *vfp){ /* anything to paint?*/
- MoveCursor(dline.row, dline.col + (int)(pfp - dline.dl));
-
- do
- Writechar((unsigned char)((vfp <= vbp && *vfp)
- ? ((*pfp = *vfp++) == TAB) ? ' ' : *pfp
- : (*pfp = ' ')), 0);
- while(++pfp <= pbp);
- }
-
- MoveCursor(dline.row, dline.col + (offset - dline.vbase));
- }
-
-
-
- /*----------------------------------------------------------------------
- Check to see if the given command is reasonably valid
-
- Args: ch -- the character to check
-
- Result: A valid command is returned, or a well know bad command is returned.
-
- ---*/
- validatekeys(ch)
- int ch;
- {
- if(F_ON(F_USE_FK,ps_global)) {
- if(ch >= 'a' && ch <= 'z')
- return(KEY_JUNK);
- } else {
- if(ch >= PF1 && ch <= PF12)
- return(KEY_JUNK);
- }
- return(ch);
- }
-
-
-
- /*----------------------------------------------------------------------
- Prepend config'd commands to keyboard input
-
- Args: ch -- pointer to storage for returned command
-
- Returns: TRUE if we're passing back a useful command, FALSE otherwise
-
- ---*/
- int
- process_config_input(ch)
- int *ch;
- {
- static char firsttime = (char) 1;
-
- /* commands in config file */
- if(ps_global->initial_cmds && *ps_global->initial_cmds) {
- /*
- * There are a few commands that may require keyboard input before
- * we enter the main command loop. That input should be interactive,
- * not from our list of initial keystrokes.
- */
- if(ps_global->dont_use_init_cmds)
- return(0);
-
- *ch = *ps_global->initial_cmds++;
- if(!*ps_global->initial_cmds && ps_global->free_initial_cmds){
- fs_give((void **)&(ps_global->free_initial_cmds));
- ps_global->initial_cmds = 0;
- }
-
- return(1);
- }
-
- if(firsttime) {
- firsttime = 0;
- if(ps_global->in_init_seq) {
- ps_global->in_init_seq = 0;
- ps_global->save_in_init_seq = 0;
- clear_cursor_pos();
- F_SET(F_USE_FK,ps_global,ps_global->orig_use_fkeys);
- /* draw screen */
- *ch = ctrl('L');
- return(1);
- }
- }
-
- return(0);
- }
-
-
-
- /*----------------------------------------------------------------------
- record and playback user keystrokes
-
- Args: ch -- the character to record
- play -- flag to tell us to return first recorded char on tape
-
- Returns: either character recorded or played back or -1 to indicate
- end of recording
-
- ---*/
- #define TAPELEN 256
-
- int
- key_recorder(ch, play)
- int ch;
- int play;
- {
- static int tape[TAPELEN];
- static long recorded = 0L;
- static short length = 0;
-
- if(play){
- ch = length ? tape[(recorded + TAPELEN - length--) % TAPELEN] : -1;
- }
- else{
- tape[recorded++ % TAPELEN] = ch;
- if(length < TAPELEN)
- length++;
- }
-
- return(ch);
- }
-